// MethodThreadPool.cpp : implementation file
//

#include "stdafx.h"
#include "kwclientcore.h"
#include "MethodThreadPool.h"
#include "MethodThread.h"
#include "BaseMethodPerformer.h"

#include "CommonLib\Guard.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMethodThreadPool

IMPLEMENT_DYNCREATE(CMethodThreadPool, CWinThread)

CMethodThreadPool::CMethodThreadPool()
{
  m_bAutoDelete = FALSE;
}

CMethodThreadPool::~CMethodThreadPool()
{
}

BOOL CMethodThreadPool::InitInstance()
{
	// TODO:  perform and per-thread initialization here
	return TRUE;
}

int CMethodThreadPool::ExitInstance()
{
	// TODO:  perform any per-thread cleanup here
	return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(CMethodThreadPool, CWinThread)
	//{{AFX_MSG_MAP(CMethodThreadPool)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
  ON_THREAD_MESSAGE(WM_APP_METHODTHREADEXITED, OnMethodThreadExited)
  ON_THREAD_MESSAGE(WM_APP_EXITTHREAD, OnExitThread)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMethodThreadPool message handlers

CMethodThreadPool * CMethodThreadPool::m_pInstance = NULL;

CMethodThreadPool * CMethodThreadPool::Instance()
{
  if (m_pInstance == NULL)
  {
    m_pInstance = (CMethodThreadPool *)AfxBeginThread(RUNTIME_CLASS(CMethodThreadPool), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
    VERIFY(m_pInstance->ResumeThread());
  }

  return m_pInstance;
}

void CMethodThreadPool::DeleteInstance()
{
  if (m_pInstance) delete m_pInstance;

  m_pInstance = NULL;
}

void CMethodThreadPool::AddMethod(BaseMethodPerformer * pPerformer)
{
  Guard guard(&m_mutexMethodThreads);

  MethodThread * pMethodThread = new MethodThread(pPerformer);
  m_MethodThreads.push_back(pMethodThread);
  pMethodThread->CreateThread();
}

LRESULT CMethodThreadPool::OnMethodThreadExited(WPARAM wParam, LPARAM lParam)
{
  Guard guard(&m_mutexMethodThreads);

  MethodThread * pMethodThread = (MethodThread *)wParam;
  m_MethodThreads.erase(std::remove(m_MethodThreads.begin(), m_MethodThreads.end(), pMethodThread), m_MethodThreads.end());
  pMethodThread->Wait();
  delete pMethodThread;

  return 0;
}

LRESULT CMethodThreadPool::OnExitThread(WPARAM wParam, LPARAM lParam)
{
  Guard guard(&m_mutexMethodThreads);

  std::list<MethodThread *>::const_iterator iter;
  for (iter = m_MethodThreads.begin();iter != m_MethodThreads.end();++iter)
  {
    MethodThread * pMethodThread = *iter;
    pMethodThread->GetpPerformer()->Cancel();
    pMethodThread->Wait();
  }

  PostQuitMessage(0);

  return 0;
}
